package com.wzdigit.wms.raw.service.inv;

import com.alibaba.fastjson.JSON;
import com.wzdigit.framework.Shift;
import com.wzdigit.wms.basic.client.request.inv.SearchGoodsMergeInfoRequest;
import com.wzdigit.wms.basic.client.request.inv.SubmitGoodsMergeRequest;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.client.response.inv.GoodsMergeInfoResponse;
import com.wzdigit.wms.basic.domain.basic.Warehouse;
import com.wzdigit.wms.basic.domain.dtos.inventory.UpdateInventoryInputDto;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.GoodsLog;
import com.wzdigit.wms.basic.domain.inventory.GoodsVersion;
import com.wzdigit.wms.basic.enums.GoodsStatusEnum;
import com.wzdigit.wms.basic.enums.IsHoldEnum;
import com.wzdigit.wms.basic.enums.OpCodeEnum;
import com.wzdigit.wms.basic.enums.QaStatusEnum;
import com.wzdigit.wms.basic.mapper.core.basic.WarehouseMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.manager.GoodsMergeMapper;
import com.wzdigit.wms.basic.service.code.GoodsVersionService;
import com.wzdigit.wms.basic.service.code.InventoryService;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.raw.service.wmscommon.core.GoodsService;
import net.dreamlu.mica.core.utils.BeanUtil;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 物料合并-服务类
 * 
 * @author yangdongjie
 * @GdnService.java
 * @2021年2月24日下午3:25:03
 */
@Service
public class GoodsMergeService {

	@Autowired
	private GoodsMergeMapper goodsMergeMapper;
	
	@Autowired
	private WarehouseMapper warehouseMapper;
	
	@Autowired
	private GoodsService goodsService;
	
	@Autowired
	private GoodsVersionService goodsVersionService;
	
	@Autowired
    private InventoryService inventoryService;
	
	/**
	 * 扫描SN
	 * 
	 * @param dto
	 * @return
	 */
	public GoodsMergeInfoResponse scanInfo(SearchGoodsMergeInfoRequest dto) {
		GoodsMergeInfoResponse goods = goodsMergeMapper.selectInfoBySn(dto.getGoodsSn());
		// 【检验1】条码不存在
		if (goods == null) {
			Shift.fatal(String.format("SN[%s]条码不存在", dto.getGoodsSn()));
		}
		// 【检验2】待入库/已拣选/已出库/在途/已报废    状态不可进行料号转换
		if(Objects.equals(goods.getStatus(), GoodsStatusEnum.WAIT_IN.code) || 
				Objects.equals(goods.getStatus(), GoodsStatusEnum.HAS_DOWN.code) || 
				Objects.equals(goods.getStatus(), GoodsStatusEnum.HAS_CHUKU.code) || 
				Objects.equals(goods.getStatus(), GoodsStatusEnum.OUT_ONLOAD.code) ||
				Objects.equals(goods.getStatus(), GoodsStatusEnum.SCRAP.code)) {
			Shift.fatal(String.format("SN[%s]状态为[%s]不可进行物料合并", goods.getGoodsSn(), GoodsStatusEnum.getEnumByCode(goods.getStatus()).enumName));
		}
		
		// 【检验3】冻结状态下的SN不能进行料号转换
		if (Objects.equals(goods.getIsHold(), IsHoldEnum.Yes.code)) {
			Shift.fatal(String.format("SN[%s]被冻结不可进行物料合并", goods.getGoodsSn()));
		}
		
		// 【检验4】物料品质状态必须为“合格”
		if (!Objects.equals(goods.getQaStatus(), QaStatusEnum.OK.code)) {
			Shift.fatal(String.format("SN[%s]品质状态为[%s]，不能进行物料合并", goods.getGoodsSn(), QaStatusEnum.getEnumByCode(goods.getQaStatus()).enumName));
		}
		
		// 扫描合并物料方式
		if(dto.getType() == 1) {
			// 【检验5】物料数量不能为0
			if(goods.getQty().signum() == 0) {
				Shift.fatal(String.format("SN[%s]数量为0，不能进行物料合并", goods.getGoodsSn()));
			}
			
			Goods targetGoods = goodsService.selectBySn(dto.getTargetGoodsSn());
			Warehouse targetWhs = warehouseMapper.selectById(targetGoods.getWhsId());
			
			// 【检验6】与目标物料所属仓库必须一致
			if(!Objects.equals(goods.getWhsId(), targetGoods.getWhsId())) {
				Shift.fatal(String.format("SN[%s]所属仓库[%s]与目标物料所属仓库[%s]不一致，不能合并", goods.getGoodsSn(), goods.getWhsName(), targetWhs.getWhsName()));
			}
			
			// 【检验7】待合并物料的属性必须和目标物料属性完全一致
			List<String> notSameAttr = new ArrayList<String>();
			if(!Objects.equals(goods.getSkuId(), targetGoods.getSkuId())) {
				notSameAttr.add("物料");
			}
			if(!Objects.equals(goods.getQaStatus(), targetGoods.getQaStatus())) {
				notSameAttr.add("品质状态");
			}
			if(!Objects.equals(goods.getVendorId(), targetGoods.getVendorId())) {
				notSameAttr.add("供应商");
			}
			if(!Objects.equals(goods.getFactory(), targetGoods.getFactory())) {
				notSameAttr.add("工厂代码");
			}
			if(!Objects.equals(goods.getInvAttr(), targetGoods.getInvAttr())) {
				notSameAttr.add("库存性质");
			}
			if(!Objects.equals(goods.getLotno(), targetGoods.getLotno())) {
				notSameAttr.add("批次号");
			}
			if(!Objects.equals(goods.getOwner(), targetGoods.getOwner())) {
				notSameAttr.add("货主");
			}
			if(notSameAttr.size() > 0) {
				Shift.fatal(String.format("SN[%s][%s]与目标物料属性不一致，不能合并", goods.getGoodsSn(), notSameAttr.toString()));
			}
		}
		return goods;
	}
	
	/**
	 * 确认提交
	 * 
	 * @param dto
	 * @param servletRequest
	 * @return
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<?> submit(SubmitGoodsMergeRequest dto, HttpServletRequest servletRequest) throws Exception {
		// ---------------------------目标物料-----------------------------
		GoodsVersion targetGoods = goodsVersionService.selectBySn(dto.getTargetGoodsSn());
		
		// 【检验1】待入库/已拣选/已出库/在途/已报废 状态不可进行料号转换
		if (Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.WAIT_IN.code)
				|| Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.HAS_DOWN.code)
				|| Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.HAS_CHUKU.code)
				|| Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.OUT_ONLOAD.code)
				|| Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.SCRAP.code)) {
			Shift.fatal(String.format("SN属性发生变更，SN[%s]状态为[%s]不可进行物料合并", targetGoods.getGoodsSn(), GoodsStatusEnum.getEnumByCode(targetGoods.getStatus()).enumName));
		}

		// 【检验2】冻结状态下的SN不能进行料号转换
		if (Objects.equals(targetGoods.getIsHold(), IsHoldEnum.Yes.code)) {
			Shift.fatal(String.format("SN属性发生变更，SN[%s]被冻结不可进行物料合并", targetGoods.getGoodsSn()));
		}

		// 【检验3】物料品质状态必须为“合格”
		if (!Objects.equals(targetGoods.getQaStatus(), QaStatusEnum.OK.code)) {
			Shift.fatal(String.format("SN属性发生变更，SN[%s]品质状态为[%s]，不能进行物料合并", targetGoods.getGoodsSn(), QaStatusEnum.getEnumByCode(targetGoods.getQaStatus()).enumName));
		}
				
		// ---------------------------合并物料-----------------------------
		List<GoodsVersion> goodsList = goodsVersionService.selectBySnList(dto.getSnList());
		// 【检验1】待入库/已拣选/已出库/在途/已报废 状态不可进行物料合并
		List<GoodsVersion> errorList = goodsList.stream().filter(t -> Objects.equals(t.getStatus(), GoodsStatusEnum.WAIT_IN.code)
				|| Objects.equals(t.getStatus(), GoodsStatusEnum.HAS_DOWN.code)
				|| Objects.equals(t.getStatus(), GoodsStatusEnum.HAS_CHUKU.code)
				|| Objects.equals(t.getStatus(), GoodsStatusEnum.OUT_ONLOAD.code)
				|| Objects.equals(t.getStatus(), GoodsStatusEnum.SCRAP.code)).collect(Collectors.toList());
		if (errorList.size() > 0) {
			List<String> errorSnList = errorList.stream().map(t -> t.getGoodsSn()).collect(Collectors.toList());
			List<Integer> statusList = errorList.stream().map(t -> t.getStatus()).collect(Collectors.toList());
			List<String> statusNameList = GoodsStatusEnum.getEnumNameByCodeList(statusList);
			Shift.fatal(String.format("SN属性发生变更，SN%s状态为%s不可进行物料合并！", errorSnList.toString(), statusNameList.toString()));
		}
		
		// 【检验2】冻结状态下的SN不能进行料号转换
		errorList = goodsList.stream().filter(t -> Objects.equals(t.getIsHold(), IsHoldEnum.Yes.code)).collect(Collectors.toList());
		if (errorList.size() > 0) {
			List<String> errorSnList = errorList.stream().map(t -> t.getGoodsSn()).collect(Collectors.toList());
			Shift.fatal(String.format("SN属性发生变更，SN%s被冻结不可进行物料合并！", errorSnList.toString()));
		}

		// 【检验3】物料品质状态必须为“合格”
		errorList = goodsList.stream().filter(t -> !Objects.equals(t.getQaStatus(), QaStatusEnum.OK.code)).collect(Collectors.toList());
		if (errorList.size() > 0) {
			List<String> errorSnList = errorList.stream().map(t -> t.getGoodsSn()).collect(Collectors.toList());
			List<Integer> qaStatusList = errorList.stream().map(t -> t.getQaStatus()).collect(Collectors.toList());
			List<String> qaStatusNameList = QaStatusEnum.getEnumNameByCodeList(qaStatusList);
			Shift.fatal(String.format("SN属性发生变更，SN%s品质状态为%s，不能进行物料合并！", errorSnList.toString(), qaStatusNameList.toString()));
		}
		
		// 【检验4】物料数量不能为0
		errorList = goodsList.stream().filter(t -> t.getQty().signum() == 0).collect(Collectors.toList());
		if (errorList.size() > 0) {
			List<String> errorSnList = errorList.stream().map(t -> t.getGoodsSn()).collect(Collectors.toList());
			Shift.fatal(String.format("SN属性发生变更，SN%s数量为0，不能进行物料合并！", errorSnList.toString()));
		}
		
		// 【检验5】与目标物料所属仓库必须一致
		errorList = goodsList.stream().filter(t -> !Objects.equals(t.getWhsId(), targetGoods.getWhsId())).collect(Collectors.toList());
		if(errorList.size() > 0) {
			List<String> errorSnList = errorList.stream().map(t -> t.getGoodsSn()).collect(Collectors.toList());
			List<Integer> whsIdList = errorList.stream().map(t -> t.getWhsId()).collect(Collectors.toList());
			List<String> whsNameList = warehouseMapper.getWhsNameByWhsIdList(whsIdList);
			Warehouse targetWhs = warehouseMapper.selectById(targetGoods.getWhsId());
			Shift.fatal(String.format("SN属性发生变更，SN%s所属仓库%s与目标物料所属仓库[%s]不一致，不能合并！", errorSnList.toString(), whsNameList.toString(), targetWhs.getWhsName()));
		}
		
		// 【检验6】待合并物料的属性必须和目标物料属性完全一致
		Map<String, List<String>> notSameAttrMap = new HashMap<>();
		for (GoodsVersion item : goodsList) {
			List<String> notSameAttr = new ArrayList<String>();
			if (!Objects.equals(item.getSkuId(), targetGoods.getSkuId())) {
				notSameAttr.add("物料");
			}
			if (!Objects.equals(item.getQaStatus(), targetGoods.getQaStatus())) {
				notSameAttr.add("品质状态");
			}
			if (!Objects.equals(item.getVendorId(), targetGoods.getVendorId())) {
				notSameAttr.add("供应商");
			}
			if (!Objects.equals(item.getFactory(), targetGoods.getFactory())) {
				notSameAttr.add("工厂代码");
			}
			if (!Objects.equals(item.getInvAttr(), targetGoods.getInvAttr())) {
				notSameAttr.add("库存性质");
			}
			if (!Objects.equals(item.getLotno(), targetGoods.getLotno())) {
				notSameAttr.add("批次号");
			}
			if (!Objects.equals(item.getOwner(), targetGoods.getOwner())) {
				notSameAttr.add("货主");
			}
			if (notSameAttr.size() > 0) {
				notSameAttrMap.put(item.getGoodsSn(), notSameAttr);
			}
		}
		if(notSameAttrMap.size() > 0) {
			Shift.fatal(String.format("SN属性发生变更，%s与目标物料属性不一致，不能合并", notSameAttrMap.toString().replaceAll("=", "")));
		}
		
		// 用户名、当前时间
		String loginName = HttpSessionUtil.getLoginName(servletRequest);
		Date date = new Date();
		
		// 所有被合并条码数量的总和
		BigDecimal qty = goodsList.stream().map(t -> t.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
		
		if(Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.WAIT_UP.code) || Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.WAIT_DOWM.code)) {
			// 目标物料SN状态=已下架或待上架
			for (GoodsVersion goods : goodsList) {
				if(Objects.equals(goods.getStatus(), GoodsStatusEnum.HAS_UP.code)) {
					// 合并物料SN状态=已上架
					// 调用【下架】服务
					removeLoc(goods, targetGoods, loginName, date);
				} else {
					updateGoodsAddLog(goods, targetGoods, loginName, date);
				}
			}
		} else if(Objects.equals(targetGoods.getStatus(), GoodsStatusEnum.HAS_UP.code)) {
			// 目标物料SN状态=已上架
			for (GoodsVersion goods : goodsList) {
				if(Objects.equals(goods.getStatus(), GoodsStatusEnum.WAIT_UP.code) || Objects.equals(goods.getStatus(), GoodsStatusEnum.WAIT_DOWM.code)) {
					// 合并物料SN状态=已下架或待上架
					// 调用【上架】服务
					bindLoc(goods, targetGoods, loginName, date);
				} else if(Objects.equals(goods.getStatus(), GoodsStatusEnum.HAS_UP.code) && !Objects.equals(goods.getLocId(), targetGoods.getLocId())) {
					// 合并物料SN状态=已上架，但库位不一致
					// 调用【移库】服务
					moveLoc(goods, targetGoods, loginName, date);
				} else {
					updateGoodsAddLog(goods, targetGoods, loginName, date);
				}
			}
		} else {
			for (GoodsVersion goods : goodsList) {
				updateGoodsAddLog(goods, targetGoods, loginName, date);
			}
		}
		
		// 【更新-->目标物料】
		String oldGoodsJson = JSON.toJSONString(targetGoods); 		// 原先的json
		targetGoods.setQty(qty);									// qty更新的阀值【+】
		targetGoods.setModifyTime(date);
		targetGoods.setModifyUser(loginName);
		goodsVersionService.updateQtyById(targetGoods);
		String newGoodsJson = JSON.toJSONString(targetGoods); 		// 更新后的json
		
		// 【新增-->目标物料日志】
		GoodsLog goodsLog = new GoodsLog();
		goodsLog.setGoodsSn(targetGoods.getGoodsSn());
		goodsLog.setOpCode(OpCodeEnum.MERGE.getCode());
		goodsLog.setReason(String.format("物料合并%s", dto.getSnList().toString()));
		goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
		goodsLog.setOperator(loginName);
		goodsLog.setCreateUser(loginName);
		goodsLog.setCreateTime(date);
		goodsService.insertGoodsLog(goodsLog);
		return new Result<>();
	}
	
	
	/**
	 * 下架
	 * 
	 * @param goods		
	 * @param targetGoods	目标条码
	 * @param userName	
	 * @param date
	 * @throws Exception
	 */
	private void removeLoc(GoodsVersion goods, GoodsVersion targetGoods, String userName, Date date) throws Exception {
		// 扣减库存
		UpdateInventoryInputDto subtractInv = new UpdateInventoryInputDto();
		subtractInv.setLocId(goods.getLocId());
		subtractInv.setWhsId(goods.getWhsId());
		subtractInv.setOwner(goods.getOwner());
		subtractInv.setSkuId(goods.getSkuId());
		subtractInv.setFactory(goods.getFactory());
		subtractInv.setVendorId(goods.getVendorId());
		subtractInv.setLotNo(goods.getLotno());
		subtractInv.setInvAttr(goods.getInvAttr());
		subtractInv.setQaStatus(goods.getQaStatus());
		subtractInv.setUnit(goods.getUnit());
		subtractInv.setQty(goods.getQty().negate());
		subtractInv.setOperator(userName);
        inventoryService.updateLocInventroy(subtractInv);
        inventoryService.updateZoneInventory(subtractInv);

        // 增加库存
        UpdateInventoryInputDto addInv = new UpdateInventoryInputDto();
        addInv.setLocId(null);
        addInv.setWhsId(goods.getWhsId());
        addInv.setOwner(goods.getOwner());
        addInv.setSkuId(goods.getSkuId());
        addInv.setFactory(goods.getFactory());
        addInv.setVendorId(goods.getVendorId());
        addInv.setLotNo(goods.getLotno());
        addInv.setInvAttr(goods.getInvAttr());
        addInv.setQaStatus(goods.getQaStatus());
        addInv.setUnit(goods.getUnit());
        addInv.setQty(goods.getQty());
        addInv.setOperator(userName);
        inventoryService.updateLocInventroy(addInv);
        inventoryService.updateZoneInventory(addInv);
        
        // 更新条码
        String oldGoodsJson = JSON.toJSONString(goods);
        goods.setQty(BigDecimal.ZERO);
        goods.setLocId(null);
        goods.setStatus(GoodsStatusEnum.WAIT_DOWM.code);
        goods.setComments(String.format("合并物料至SN[%s]", targetGoods.getGoodsSn()));
        goods.setModifyTime(date);
        goods.setModifyUser(userName);
        goodsVersionService.updateById(goods);
        String newGoodsJson = JSON.toJSONString(goods);
        
        Goods item = new Goods();
        BeanUtil.copyNonNull(goods, item);
		goodsService.updateLocIdAndStatusById(item);
		
		// 新增日志
		GoodsLog goodsLog = new GoodsLog();
		goodsLog.setGoodsSn(goods.getGoodsSn());
		goodsLog.setOpCode(OpCodeEnum.MERGE.getCode());
		goodsLog.setReason(String.format("下架，物料合并，合并至目标SN[%s]", targetGoods.getGoodsSn()));
		goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
		goodsLog.setCreateTime(date);
		goodsLog.setOperator(userName);
		goodsLog.setCreateUser(userName);
		goodsService.insertGoodsLog(goodsLog);
	}
	
	/**
	 * 上架
	 * 
	 * @param goods
	 * @param targetGoods	目标条码
	 * @param userName
	 * @param date
	 * @throws Exception
	 */
	private void bindLoc(GoodsVersion goods, GoodsVersion targetGoods, String userName, Date date) throws Exception {
		// 扣减库存
		UpdateInventoryInputDto subtractInv = new UpdateInventoryInputDto();
		subtractInv.setLocId(null);
		subtractInv.setWhsId(goods.getWhsId());
		subtractInv.setOwner(goods.getOwner());
		subtractInv.setSkuId(goods.getSkuId());
		subtractInv.setFactory(goods.getFactory());
		subtractInv.setVendorId(goods.getVendorId());
		subtractInv.setLotNo(goods.getLotno());
		subtractInv.setInvAttr(goods.getInvAttr());
		subtractInv.setQaStatus(goods.getQaStatus());
		subtractInv.setUnit(goods.getUnit());
		subtractInv.setQty(goods.getQty().negate());
		subtractInv.setOperator(userName);
		inventoryService.updateLocInventroy(subtractInv);
		inventoryService.updateZoneInventory(subtractInv);

		// 增加库存
		UpdateInventoryInputDto addInv = new UpdateInventoryInputDto();
		addInv.setLocId(targetGoods.getLocId());
		addInv.setWhsId(goods.getWhsId());
		addInv.setOwner(goods.getOwner());
		addInv.setSkuId(goods.getSkuId());
		addInv.setFactory(goods.getFactory());
		addInv.setVendorId(goods.getVendorId());
		addInv.setLotNo(goods.getLotno());
		addInv.setInvAttr(goods.getInvAttr());
		addInv.setQaStatus(goods.getQaStatus());
		addInv.setUnit(goods.getUnit());
		addInv.setQty(goods.getQty());
		addInv.setOperator(userName);
		inventoryService.updateLocInventroy(addInv);
		inventoryService.updateZoneInventory(addInv);
		
		// 更新条码
        String oldGoodsJson = JSON.toJSONString(goods);
        goods.setQty(BigDecimal.ZERO);
        goods.setLocId(targetGoods.getLocId());
        goods.setStatus(GoodsStatusEnum.HAS_UP.code);
        goods.setComments(String.format("合并物料至SN[%s]", targetGoods.getGoodsSn()));
        goods.setModifyTime(date);
        goods.setModifyUser(userName);
        goodsVersionService.updateById(goods);
		String newGoodsJson = JSON.toJSONString(goods);
		
		// 新增日志
		GoodsLog goodsLog = new GoodsLog();
		goodsLog.setGoodsSn(goods.getGoodsSn());
		goodsLog.setOpCode(OpCodeEnum.MERGE.getCode());
		goodsLog.setReason(String.format("上架，物料合并，合并至目标SN[%s]", targetGoods.getGoodsSn()));
		goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
		goodsLog.setCreateTime(date);
		goodsLog.setOperator(userName);
		goodsLog.setCreateUser(userName);
		goodsService.insertGoodsLog(goodsLog);
	}
	
	/**
	 * 移库
	 * 
	 * @param goods
	 * @param targetGoods	目标条码
	 * @param userName
	 * @param date
	 * @throws Exception
	 */
	private void moveLoc(GoodsVersion goods, GoodsVersion targetGoods, String userName, Date date) throws Exception {
		// 扣减库存
		UpdateInventoryInputDto subtractInv = new UpdateInventoryInputDto();
		subtractInv.setLocId(goods.getLocId());
		subtractInv.setWhsId(goods.getWhsId());
		subtractInv.setOwner(goods.getOwner());
		subtractInv.setSkuId(goods.getSkuId());
		subtractInv.setFactory(goods.getFactory());
		subtractInv.setVendorId(goods.getVendorId());
		subtractInv.setLotNo(goods.getLotno());
		subtractInv.setInvAttr(goods.getInvAttr());
		subtractInv.setQaStatus(goods.getQaStatus());
		subtractInv.setUnit(goods.getUnit());
		subtractInv.setQty(goods.getQty().negate());
		subtractInv.setOperator(userName);
        inventoryService.updateLocInventroy(subtractInv);
        inventoryService.updateZoneInventory(subtractInv);

        // 增加库存
        UpdateInventoryInputDto addInv = new UpdateInventoryInputDto();
        addInv.setLocId(targetGoods.getLocId());
		addInv.setWhsId(goods.getWhsId());
		addInv.setOwner(goods.getOwner());
		addInv.setSkuId(goods.getSkuId());
		addInv.setFactory(goods.getFactory());
		addInv.setVendorId(goods.getVendorId());
		addInv.setLotNo(goods.getLotno());
		addInv.setInvAttr(goods.getInvAttr());
		addInv.setQaStatus(goods.getQaStatus());
		addInv.setUnit(goods.getUnit());
		addInv.setQty(goods.getQty());
		addInv.setOperator(userName);
		inventoryService.updateLocInventroy(addInv);
		inventoryService.updateZoneInventory(addInv);
        
		// 更新条码
        String oldGoodsJson = JSON.toJSONString(goods);
        goods.setQty(BigDecimal.ZERO);
        goods.setLocId(targetGoods.getLocId());
        goods.setComments(String.format("合并物料至SN[%s]", targetGoods.getGoodsSn()));
        goods.setModifyTime(date);
        goods.setModifyUser(userName);
        goodsVersionService.updateById(goods);
		String newGoodsJson = JSON.toJSONString(goods);
		
		// 新增日志
		GoodsLog goodsLog = new GoodsLog();
		goodsLog.setGoodsSn(goods.getGoodsSn());
		goodsLog.setOpCode(OpCodeEnum.MERGE.getCode());
		goodsLog.setReason(String.format("移库，物料合并，合并至目标SN[%s]", targetGoods.getGoodsSn()));
		goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
		goodsLog.setCreateTime(date);
		goodsLog.setOperator(userName);
		goodsLog.setCreateUser(userName);
		goodsService.insertGoodsLog(goodsLog);
	}
	
	/**
	 * 普通合并
	 * 
	 * @param goods
	 * @param targetGoods	目标条码
	 * @param userName
	 * @param date
	 * @throws Exception
	 */
	private void updateGoodsAddLog(GoodsVersion goods, GoodsVersion targetGoods, String userName, Date date) throws Exception {
        // 更新条码
        String oldGoodsJson = JSON.toJSONString(goods);
        goods.setQty(BigDecimal.ZERO);
        goods.setComments(String.format("合并物料至SN[%s]", targetGoods.getGoodsSn()));
        goods.setModifyTime(date);
        goods.setModifyUser(userName);
		goodsVersionService.updateById(goods);
		String newGoodsJson = JSON.toJSONString(goods);
		
		// 新增日志
		GoodsLog goodsLog = new GoodsLog();
		goodsLog.setGoodsSn(goods.getGoodsSn());
		goodsLog.setOpCode(OpCodeEnum.MERGE.getCode());
		goodsLog.setReason(String.format("物料合并，合并至目标SN[%s]", targetGoods.getGoodsSn()));
		goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
		goodsLog.setCreateTime(date);
		goodsLog.setOperator(userName);
		goodsLog.setCreateUser(userName);
		goodsService.insertGoodsLog(goodsLog);
	}
}
